package org.singledog.permission.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.singledog.permission.annotation.Permission;
import org.singledog.permission.annotation.PermissionScan;
import org.singledog.permission.core.PermissionApplicationContext;
import org.singledog.permission.core.PermissionSource;
import org.singledog.permission.utils.ScanClassUtil;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * {@link Permission}的注册类，通过{@link PermissionScan}注解注册
 *
 * @author liuzheming
 * @since 2021.9.14
 */
@Slf4j
public class PermissionScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {

    private ResourceLoader resourceLoader;

    /**
     * 权限注册
     *
     * @param importingClassMetadata {@link AnnotationMetadata}
     * @param registry               {@link BeanDefinitionRegistry}
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(PermissionScan.class.getName());
        String[] packages = (String[]) annotationAttributes.get("value");
        if (packages != null && packages.length > 0) {
            for (String aPackage :packages){
                Set<Class<?>> classSet = ScanClassUtil.getClasses(aPackage);
                for (Class<?> aClass : classSet) {
                    Method[] declaredMethods = aClass.getDeclaredMethods();
                    for (Method declaredMethod : declaredMethods) {
                        if (declaredMethod.isAnnotationPresent(Permission.class)) {
                            Permission annotation = AnnotationUtils.getAnnotation(declaredMethod, Permission.class);
                            List<PermissionSource> permissions = PermissionApplicationContext.getPermissionUri(annotation.value() + "/" + annotation.method().toLowerCase());
                            if (permissions == null) {
                                if(StringUtils.isNotBlank(annotation.permission())) {
                                    List<PermissionSource> permissionList = Arrays.stream(annotation.permission().split(",")).map(c -> new PermissionSource(c)).collect(Collectors.toList());
                                    PermissionApplicationContext.addPermissionUri(annotation.value() + "/" + annotation.method().toLowerCase(), permissionList);
                                }
                            }
                        }
                    }
                }
            }
        }
    }


    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}